Wouldn't it be nice if you had the ability to create procedures in Visual Basic that you could call like standard DLLs? Well, guess what? Part of Visual Basic 4.0 has that exact capability. It's called In Process and Out of Process servers.
As a brief refresher, in the previous chapter, you created a class module and then compiled and installed this new class into the system registry. A class defines what an object is or can become. The actual object is created when you call its class or
define a class in a procedure. You can call a class multiple times and create multiple instances of this class.
When you define a class, you specify what actions it can take. These actions are called methods. Most classes also have static fields where values can be stored; these fields are called properties. When you insert, for example, a text box onto a form
and then press F4, a dialog box that displays the current properties of the text box control appears. Double-clicking on the text box causes a code window to appear. This code window contains a combo box that lists the events from which you can choose;
these events are the methods for this object.
You can now create this same capability for extensions to Visual Basic or for use by other applications within Visual Basic. You can compile a library of functions that you can encapsulate into an In Process server that can in turn be called by multiple
applications. Suppose that your applications always format the header and footer the same way when using the Printer object. You could develop a routine that formats the header and footer by accepting parameters and then call that routine from all
applications that you develop. You can use this same capability to extend the operating system as well as your development tools. For example, you can now (using Windows NT 3.51 and above and Windows 95) develop an application as you would develop a
general purpose query. When this application is installed, you can choose to install it into the system registry as a object. Then other applications that are OLE 2.0-compliant can paste your object into their applications.
OLE objects that are defined by In Process servers use the basic Windows messaging structure, which involves a server and a client(s) that calls the methods and properties of the server.
OLE servers and OLE itself are not as difficult to use as some people in the computer industry would lead you to believe. If you are comfortable programming in Visual Basic, you can learn to use OLE effectively. I frequently encounter smart, capable
individuals who don't try some of the new technology because someone wrote an article about how difficult it is to implement compared with what you get out of it. Experiment with this technology and try it out for yourself.
There have always been protracted discussions about the philosophy of software development. C programmers do the really hard stuff, COBOL programmers work on the everyday stuff, and so on. My advice to you is don't put yourself into a box, and don't let
others put you in a box about new ideas. The whole purpose of OLE is simple: share data and code; reduce cost; and improve reliability.
OLE, as the previous chapter discussed, is not as widespread in non-shrink-wrapped applications as it is in shrink-wrapped applications. I think this is partly due to competition among vendors of shrink-wrapped applications in their feature wars. To be
fair, OLE is not yet a mature technology, but that does not mean you should not use it. By the time you get a good application up and implemented, OLE will be much further along.
In my experience, most organizations take considerable time to implement new technology. For example, if your organization has 500 employees and has been in existence for awhile, then most likely you will have a wide array of computer types and users.
Most organizations that I have dealt with cannot afford to throw away the equipment and training they have whenever a new technology comes along.
There is also an element of risk in investing in learning OLE and developing some applications using it because there's no way of knowing whether it will become a standard. I have absolutely no doubts that object technology is going to dominate software
in the future, and I think Microsoft with OLE will have a large piece of that market when it matures. Even so, if some other concept becomes a standard, what you learn with this technology will give you a leg up on those that are waiting until the
technology matures.
Some pundits believe that programming will become a task of coordinating multiple software components over the next few years. An OLE object can be a software component. Programmers are doing significant new things with OLE objects. Have you ever
written any client/server applications in Visual Basic? If you have, you know how frustrating it was with version 3. Version 4 has remote data objects (RDO). The RDO control is an OLE object for connecting to remote data that is ODBC-compliant. Not only
does the RDO object simplify the connection to remote data but it dramatically improves speed of the connection as well. RDO is a good example of what OLE objects can do: improve access, improve reliability, reduce programming time, and improve
performance. If you start using OLE now in a meaningful way, then, as the standard matures, you will have in house expertise and working applications that will increase reliability, lower cost, and allow data to be shared more easily.
To see how OLE In Process servers work, try the following procedure. This procedure shows you how to create a server that displays copyright information and does a couple of other things for clients that call it. Follow these steps to create the OLE
server:
Figure 19.1. The Project tab of a Visual Basic form.
The Sub Main procedure you chose in step 4 above is where you can establish start-up code prior to initialization if you need or want to do so. To make this procedure work, you first need to create a code module. Follow these steps:
Figure 19.2. The default Sub Main procedure.
Now you need to add a class module. Remember from Chapter 18 that a class defines an object. The object itself does not get created until it is called. Then Visual Basic uses the specifications defined in the class module to create a specific instance
of this class as your particular object. The OLE server creates a reference to the specific object that is created at call time. In other words, the only thing you are creating here is the outline or parameters of your object. When the class is called, a
specific object that has its own life will be created using the parameters that you define here. To create a class module, follow these steps:
The Name property specifies the name of the class. Setting the Public property to TRUE means you can see the class from other applications. Setting the Instancing property to 2-creatable multiuse allows the OLE server to create multiple objects. (Note
that it is sometimes useful to be able to restrict an object instance to one call. You might want to make this restriction if, for example, you were to use OLE to do maintenance on a database.) These properties create a framework for your object.
Now you need to define properties and methods. If you want your properties and methods to be public, they must be defined as such. There are cases, even in an OLE server, in which you might want private variables and procedures instead. Users can read
private variables, but they cannot change these variables.
Follow these steps to define the properties and methods:
Figure 19.3. The object properties.
Figure 19.4. Testing the Visual Basic object.
To create the client application that will call the server you just created, follow these steps:
Figure 19.5. Defining the client object.
To create a link or reference between this client application and the server that you are calling, follow these steps:
Figure 19.6. Including a reference in your client object application.
Figure 19.7. Browsing objects in our OLE server object.
Figure 19.8. Testing the client object.
Figure 19.9. A running client accessing the In Process server.
This example worked because you had both the client and the server applications running at the same time. Closing the OLE server and running the client application produces an error. To prevent this error from occurring, you need to register the server
application into the system registry.
To register your OLE server on the same computer you created it on, choose File | Make OLE DLL file. Enter an appropriate name and the system will register the In Process server in the system registry as shown in Figure 19.10.
Figure 19.10. Registering the In Process server.
You can also create an OLE server as an executable file for installation onto a target machine by choosing File | Make EXE. When you install on your target machine, enter the following in the Run command dialog box:
C:\MyProg.EXE /REGSERVER
Figure 19.11 shows how the executable file named TARGET.EXE would look in the registry.
Figure 19.11. Registering external In Process servers.
The computer shown in Figure 19.11 now has two OLE servers that do the same thing installed on it. The COPYR.DLL is located in the C:\OLESERV directory and now also is TARGET.EXE. When you run the client application again, you must first terminate the
instance of Visual Basic that is running your OLE server. Then go into your client application and remove the reference to MyCopyDemo (you called your DLL COPYR.DLL). Using the Browse button, point to COPYR.DLL in the C:\OLESERV directory. When you run the
application again and click on the Show Copyright button (now without the other instance of Visual Basic running), you see the screen shown in Figure 19.12. Save this OLE server project and client project as separate projects.
Figure 19.12. A client application accessing a built-in In Process server.
The previous application examples are defined as In Process servers because they execute in the same process space as the client that called them. In the example, you knew ahead of time that you wanted to link the copyright server to your application,
so you could include a reference to it. What if that were not the case? Or what if we wanted to use some pre-existing OLE servers?
As demonstrated in the previous example, you can dramatically expand OLE servers to perform all kinds of tasks. Before you can put this technology to work, however, you need to ask yourself some questions. I do not have the space in this chapter to
define all of the following characteristics, but you can use the following questions as a brief checklist of issues to resolve prior to creating your OLE servers:
Answering all these questions will guide you to a proper design. You also need to consider the normal programming concerns such as determining how many resources the application will consume, figuring out how large the in-memory image will be, and
deciding whether to use many small objects or large DLLs that contain many objects. The answers to these questions are, of course, dependent upon the application involved.
When you start to answer the questions mentioned previously, it is helpful to look at objects in another light. Traditionally, good programming style has dictated using parametric design in many of the algorithms that you create. This design means that
a set of given values that a program may use to display or get data are not coded into the program but are established in a Setup function somewhere within the system. In this way, you can think of objects as stored procedures. Like anything that you store
and retrieve, you can also link these objects together into a database-like hierarchy.
When I use the term stored procedure, I don't mean it in the same vein that this term is used in SQL databases. These procedures are limited in function to specific database activities and are tied to very specific applications. Objects are like stored
procedures in that they do not reside in the client software, but, unlike stored procedures, they can be called and used by a wide variety of applications and can be used throughout the system.
In traditional database nomenclature, you can have flat files, and you can have hierarchical files. This is also true of objects. You could create a set of objects that are all flat in that no one object depends upon the other. For example, you could
have a set of objects that you use with the printer object. You could have a page header object, a page footer object, a print logo object, and so forth. You could call each one of these objects directly.
A hierarchical file could be something like an inventory class. The top or main class could be Inventory. Transactions could be a subclass. You could tie the Transactions subclass to the Inventory class with a Collection class. Therefore, when you refer
to the Inventory class, you automatically get the Transactions class as well. For instance, in the previous example, you could get to the MSG1 object by defining a new instance of CopyR. This is because MSG1 is encapsulated within CopyR, each new instance
of CopyR also creates a reference to the subclasses within this object. If you defined a new instance of Inventory, you would get all of the methods and properties of Inventory as well as all of the subclasses, properties, and methods of Transactions.
Again, this is because Transactions as a class is encapsulated within Inventory. You could extend this idea dramatically to nest classes several levels deep. Of course, when you have several levels of classes, you have slower performance (because there are
more classes to go through to find objects) and a larger program image size.
Keep in mind the purpose of your objects. If they become too specific, you may want to weigh the time it takes to create an object class versus the time it takes to embed the code in your application. A class or object should be a code fragment that has
multiple applications and uses.
Another example may give you a better idea of how this process works. As you did in the previous example, you need to set up the project somewhat differently in order to create an OLE server. Consider Figure 19.13.
Figure 19.13. Defining an In Process server.
The first thing you need to do is to enter a name in the Project name box. At this point in the process, some planning is worthwhile. Remember that the project name needs to be unique when you install it into the system registry. In the previous
example, you created a class CopyR. To use this class in a new client application, you could use the following code fragment:
PUBLIC MyNewObject As MyCopyRight.CopyR
This kind of code is called a fully qualified class name because it contains the project name (MyCopyRight) and the class you are creating (CopyR). Remember that most of your users' Windows applications will now have multiple definitions of unique
classes for a given application. For example, I recently read that Excel 5.0 has over 100 object classes of its own. If you were to define a class that had the same name as your application, your application could crash. For this reason, you should use
fully qualified class names in addition to planning out what class names you want to use.
Figure 19.14 shows an example of how not to name your projects. Remember when you created two objects earlier in the chapter and named one COPYR.DLL and the other TARGET.EXE? Next, you installed TARGET.EXE with the /REGSERVER option. As a result, you
ended up with two of the same object. You can prevent such situations by planning your names and controlling versions and compiles. Even though one of our compiles was a DLL and another was as an EXE, both used the same object name. The object name is what
you see here in the Visual Basic reference window.
Figure 19.14. Duplicate In Process servers.
In the Start Mode box, make sure you select the OLE server option in order to create your server first. Visual Basic creates temporary entries into the system registry and creates links to any client provided that you execute two copies of Visual Basic
in Design mode, the first copy being your OLE server and the second copy being your client, and perform the proper setting with the Reference function. Although you may not yet want to compile this application of your server and link it into the registry,
note that Visual Basic creates temporary links for you so that you can test your client applications. This means that you do not have to permanently link server applications until you are ready to do so.
You would most likely want to make sure that your OLE server compiles and runs before launching a client to test it. This feature is built into the Visual Basic Design mode. Normally, a compiled OLE server would not start until the client called it.
When you set the Start mode to OLE server, Visual Basic knows to keep your project running even though no calls are being made to it. Otherwise, the project would end immediately because there are no clients requesting it. In Development mode, it is useful
to be able to execute two copies of Visual Basic, one running the server and the other running the client. If you have an OLE server running in Design mode and a client that calls it, stopping your OLE server will produce an error message that notifies you
that you have dependent applications.
The vast majority of the time your start-up form will contain a Sub Main() procedure as its primary start-up mode. If you need a start-up form, you should display that form from Sub Main(). Be sure that Sub Main() is not in a class module. Also, use
caution when putting forms into OLE servers. Many developers think most, if not all, of the user interface should be in the client application.
As discussed briefly in the previous example, another distinguishing feature of an OLE server is that it contains at least one class module with its Public property set to TRUE. Clients can read and write to the procedures and properties in the class
module that have their Public properties set to TRUE. This applies to variables, procedures, and functions.
Of course, because the OLE server is a project like any other Visual Basic project, you can extend it. To demonstrate this fact, try adding an initialize procedure for when the server you created earlier starts and ends. Follow these steps:
Figure 19.15. Extending an In Process server.
Figure 19.16. Running the In Process server with new extensions.
Figure 19.17. Expanding the In Process server functionality.
As you can see, you can extend existing OLE servers quite easily. Try adding another method to the OLE server by following these steps:
Figure 19.18. Adding a new method to the OLE server.
In order to create a complete OLE server, you should add a help file to assist end users and other developers that want to reuse your code. (If the code you are contemplating for an OLE server cannot be reused, you should consider whether you need to
create an OLE server at all.) Follow these steps to add a help file:
Figure 19.19. Adding a help file to your In Process server.
Figure 19.20. Browsing the In Process server.
Figure 19.21. Browsing elements of our server.
The confines of this chapter do not allow me to describe all of the features you could add to your OLE server. Two important features you should add are error handling and version control. The Microsoft Visual Basic manuals present some information on
these subjects, but it is best to experiment for yourself and keep in mind the problems you can avoid downstream by building in code for these two additional areas.
I could write a very long book just on OLE programming. Because OLE is not the main focus of this book, I will stop here with a couple of additional thoughts that may be helpful. Hopefully, you can see the tremendous potential in OLE and OLE
programming. Yes, it is new. Yes, it has constraints. Yes, it has some bugs. However, I believe Microsoft will be adept at addressing these issues. If you want to move your organization forward and if you are tired of programming the same old stuff over
and over again, OLE is a way to resolve both issues in an elegant fashion.
Happy coding!